﻿using System;
using System.Windows;

namespace Black.SurfaceToolkit.Tools
{
    #region Classe Application

    /// <summary>
    /// Classe d'extension pour la classe <see cref="T:System.Windows.Application" />.
    /// </summary>
    public static class ApplicationExtensions
    {
        #region Fonctions statiques publiques

        /// <summary>
        /// Invoque de façon sécurisée l'action spécifiée dans le thread graphique de l'application spécifiée.
        /// </summary>
        /// <param name="p_oApplication">Application dont le thread graphique exécutera l'action.</param>
        /// <param name="p_oCode">Action à effectuer.</param>
        public static void InvokeSafe(this Application p_oApplication, Action p_oCode)
        {
            if (!p_oApplication.Dispatcher.CheckAccess())
                p_oApplication.Dispatcher.BeginInvoke(p_oCode);
            else
                p_oCode.Invoke();
        }

        #endregion
    }

    #endregion

    #region Classe Double

    /// <summary>
    /// Classe d'extension pour la classe <see cref="T:System.Double" />.
    /// </summary>
    public static class DoubleExtensions
    {
        #region Fonctions statiques publiques

        /// <summary>
        /// Effectue une réduction de la valeur de l'angle spécifié.
        /// </summary>
        /// <param name="p_dAngle">Valeur de l'angle à réduire (en degrés).</param>
        /// <returns><paramref name="p_dAngle" /> réduit.</returns>
        public static double CropAngle(this double p_dAngle)
        {
            return (Utils.CropAngle(p_dAngle));
        }

        #endregion
    }

    #endregion

    #region Classe Points

    /// <summary>
    /// Classe d'extension pour la classe <see cref="T:System.Windows.Point" />.
    /// </summary>
    public static class PointExtensions
    {
        #region Fonctions statiques publiques

        /// <summary>
        /// Obtient une valeur indiquant si un point référencé et un élement spécifiés sont en collisions.
        /// </summary>
        /// <param name="p_oPoint">Point à tester.</param>
        /// <param name="p_oElement">Elément à test.</param>
        /// <param name="p_oReference">Référence de calcul.</param>
        /// <returns><see langword="true" /> si <paramref name="p_oPoint" /> référencé dans <paramref name="p_oReference" /> est dans <paramref name="p_oElement" />, <see langword="false" /> sinon.</returns>
        public static bool Intersect(this Point p_oPoint, FrameworkElement p_oElement, FrameworkElement p_oReference)
        {
            return (Utils.Intersect(p_oPoint, p_oElement, p_oReference));
        }

        /// <summary>
        /// Obtient une valeur indiquant si le point spécifié est dans le rectangle spécifié.
        /// </summary>
        /// <param name="p_oPoint">Point à tester.</param>
        /// <param name="p_oRect">Rectangle à tester.</param>
        /// <returns><see langword="true" /> si <paramref name="p_oPoint" /> est dans <paramref name="p_oRect" />, <see langword="false" /> sinon.</returns>
        public static bool PointInRect(this Point p_oPoint, Rect p_oRect)
        {
            return (Utils.PointInRect(p_oPoint, p_oRect));
        }

        #endregion
    }

    #endregion

    #region Classe FrameworkElement

    /// <summary>
    /// Classe d'extension pour la classe <see cref="T:System.Windows.FrameworkElement" />.
    /// </summary>
    public static class FrameworkElementExtensions
    {
        #region Fonctions statiques publiques

        /// <summary>
        /// Obtient une valeur indiquant si un point référencé et un élement spécifiés sont en collisions.
        /// </summary>
        /// <param name="p_oElement">Elément à test.</param>
        /// <param name="p_oPoint">Point à tester.</param>
        /// <param name="p_oReference">Référence de calcul.</param>
        /// <returns><see langword="true" /> si <paramref name="p_oPoint" /> référencé dans <paramref name="p_oReference" /> est dans <paramref name="p_oElement" />, <see langword="false" /> sinon.</returns>
        public static bool Intersect(this FrameworkElement p_oElement, Point p_oPoint, FrameworkElement p_oReference)
        {
            return (Utils.Intersect(p_oPoint, p_oElement, p_oReference));
        }

        /// <summary>
        /// Obtient une valeur indiquant si deux élements référencés spécifiés sont en collisions.
        /// </summary>
        /// <param name="p_oElement1">Premier élément à tester.</param>
        /// <param name="p_oElement2">Second élément à tester.</param>
        /// <param name="p_oReference">Référence de calcul.</param>
        /// <returns><see langword="true" /> si <paramref name="p_oElement1" /> et <paramref name="p_oElement2" /> référencés dans <paramref name="p_oReference" /> ont une intersection non vide, <see langword="false" /> sinon.</returns>
        public static bool Intersect(this FrameworkElement p_oElement1, FrameworkElement p_oElement2, FrameworkElement p_oReference)
        {
            return (Utils.Intersect(p_oElement1, p_oElement2, p_oReference));
        }

        #endregion
    }

    #endregion

    #region Classe UIElement

    /// <summary>
    /// Classe d'extension pour la classe <see cref="T:System.Windows.UIElement" />.
    /// </summary>
    public static class UIElementExtensions
    {
        #region Fonctions statiques publiques
        
        /// <summary>
        /// Invoque de façon sécurisée l'action spécifiée dans le thread graphique de l'élément spécifié.
        /// </summary>
        /// <param name="p_oElement">Elément dont le thread graphique exécutera l'action.</param>
        /// <param name="p_oCode">Action à effectuer.</param>
        public static void InvokeSafe(this UIElement p_oElement, Action p_oCode)
        {
            if (p_oElement.Dispatcher.Thread.ThreadState == System.Threading.ThreadState.Running)
                p_oElement.Dispatcher.BeginInvoke(p_oCode);
            else if (p_oElement.Dispatcher.Thread.IsAlive)
                p_oElement.Dispatcher.Invoke(p_oCode);
            else
                p_oCode.Invoke();
        }

        #endregion
    }

    #endregion

    #region Classe Rect

    /// <summary>
    /// Classe d'extension pour la classe <see cref="T:System.Windows.Rect" />.
    /// </summary>
    public static class RectExtensions
    {
        #region Fonctions statiques publiques

        /// <summary>
        /// Obtient une valeur indiquant si le point spécifié est dans le rectangle spécifié.
        /// </summary>
        /// <param name="p_oRect">Rectangle à tester.</param>
        /// <param name="p_oPoint">Point à tester.</param>
        /// <returns><see langword="true" /> si <paramref name="p_oPoint" /> est dans <paramref name="p_oRect" />, <see langword="false" /> sinon.</returns>
        public static bool PointInRect(this Rect p_oRect, Point p_oPoint)
        {
            return (Utils.PointInRect(p_oPoint, p_oRect));
        }

        #endregion
    }

    #endregion
}
